<template>
  <div class="page-table">
    <template v-if="dataSource && dataSource.length > 0">
      <div class="table-box">
        <u-table
          ref="uTable"
          size="mini"
          :data="dataSource"
          :height="height"
          :row-height="rowHeight"
          style="width: 100%;"
          border
          @header-dragend="onColumnWidthChange"
        >
          <template slot="empty">暂无数据</template>
          <u-table-column
            v-for="(item, i) in columns"
            :key="`${item.title}-${i}`"
            :resizable="true"
            :width="
              columnWidthData[item.title] ? columnWidthData[item.title] : null
            "
            :show-overflow-tooltip="false"
            :prop="item.title"
            :label="item.title"
            remote-sort
          >
            <div slot="header" class="header-cell">
              <div class="header-label">
                {{ item.title }}
              </div>
              <span v-if="isSortable" class="caret-wrapper">
                <em
                  :ref="`asc_${i}`"
                  class="sort-caret ascending"
                  :class="{
                    active: item.sort === 'asc',
                  }"
                  @click="onSortIconClick(item, 'asc', i)"
                ></em>
                <em
                  :ref="`desc_${i}`"
                  class="sort-caret descending"
                  :class="{
                    active: item.sort === 'desc',
                  }"
                  @click="onSortIconClick(item, 'desc', i)"
                ></em>
              </span>
            </div>
            <template #default="{ row }">
              <ToolTip
                :content="row[item.title]"
                :width="columnWidthData[item.title]"
                :unit-width="unitWidth"
              >
                {{ row[item.title] }}
              </ToolTip>
            </template>
          </u-table-column>
        </u-table>
      </div>
      <div v-if="!noPage" class="page-box">
        <a-pagination
          v-model="currentPage"
          size="small"
          :disabled="pageDisabled"
          :total="total"
          :default-page-size="50"
          :page-size="pageSize"
          :page-size-options="pageSizeOptions"
          @change="onShowNumberChange"
          @showSizeChange="onShowSizeChange"
        />
      </div>
    </template>
  </div>
</template>
<script lang="ts">
import { isArray } from 'lodash'
// @ts-ignore
import { UTable, UTableColumn } from 'umy-table'
import 'umy-table/lib/theme-chalk/index.css'
import Vue from 'vue'
import { getFormatValue } from '@/util/common'
import ToolTip from '@/components/pageTable/ToolTip.vue'

export default Vue.extend({
  components: {
    UTable,
    UTableColumn,
    ToolTip,
  },
  props: {
    isSortable: {
      type: Boolean,
      default() {
        return false
      },
    },
    pageDisabled: {
      type: Boolean,
      default() {
        return false
      },
    },
    noPage: {
      type: Boolean,
      default() {
        return false
      },
    },
    size: {
      type: String,
      default() {
        return 'small'
      },
    },
    config: {
      type: Object,
      default() {
        return null
      },
    },
  },
  data() {
    return {
      sortIndex: -1,
      columns: [],
      sortKey: '',
      sortMode: '',
      rowHeight: 0,
      unitWidth: 80,
      pageSize: 50,
      currentPage: 1,
      columnMinWidth: 80,
      height: 300,
      pageSizeOptions: ['10', '20', '30', '40', '50'],
      columnWidthData: {},
    }
  },
  computed: {
    total() {
      const config = this.config as any
      return config && config.chartOptions
        ? config.chartOptions.totalElements || 0
        : 0
    },
    dataSource() {
      const config = this.config as any
      // 对百分比、科学计数法两种数据格式进行处理
      const numberFormat = config?.numberFormat
      if (
        config &&
        config.chartOptions &&
        isArray(config.chartOptions.value) &&
        config.chartOptions.value.length > 0
      ) {
        return config.chartOptions.value?.map((value: any) => {
          config.chartOptions?.columns?.forEach((col: string) => {
            if (numberFormat && numberFormat[col]) {
              const { action, digit } = numberFormat[col]
              value[col] = value[col]
                ? getFormatValue(value[col], action, digit)
                : value[col] // 0直接展示为0即可
            }
          })
          return value
        })
      }
      return []
    },
  },
  watch: {
    config: {
      deep: true,
      immediate: true,
      handler(newValue: any) {
        if (newValue && newValue.chartOptions) {
          if (newValue.chartOptions.curPage) {
            this.currentPage = newValue.chartOptions.curPage
          }
          if (newValue.chartOptions.pageSize) {
            this.pageSize = newValue.chartOptions.pageSize
          }
          if (newValue.chartOptions.sortCol?.length > 0) {
            // 初始化排序字段信息
            this.sortKey = newValue.chartOptions.sortCol[0].name
            this.sortMode = newValue.chartOptions.sortCol[0].sort
            this.sortIndex = (newValue.chartOptions.columns || []).findIndex(
              (column: string) => column === this.sortKey
            )
          }
          this.columns = this.getColumns()
          this.unitWidth = this.getUnitWidth()
          this.height = this.calcTableHeight()
          this.getColumnWidthData()
        }
      },
    },
  },
  mounted() {
    setTimeout(() => {
      this.unitWidth = this.getUnitWidth()
      this.height = this.calcTableHeight()
      this.columns = this.getColumns()
    }, 10)
  },
  methods: {
    getColumns() {
      const config = this.config as any
      if (
        config &&
        config.chartOptions &&
        isArray(config.chartOptions.columns) &&
        config.chartOptions.columns.length > 0
      ) {
        return config.chartOptions.columns.reduce(
          (rec: Array<any>, item: string) => {
            rec.push({
              title: item,
              dataIndex: item,
              key: item,
              sort: this.sortKey === item ? this.sortMode : '',
            })
            return rec
          },
          []
        )
      }
      return []
    },
    onSortIconClick(item: any, sortMode: string, index: number) {
      if (index !== this.sortIndex || this.sortMode !== sortMode) {
        if (this.sortIndex > -1) {
          const ascElement = this.$refs[`asc_${this.sortIndex}`]
          const descElement = this.$refs[`desc_${this.sortIndex}`]
          if (ascElement && isArray(ascElement) && ascElement.length > 0) {
            ;(ascElement[0] as HTMLElement).classList.remove('active')
          }
          if (descElement && isArray(descElement) && descElement.length > 0) {
            ;(descElement[0] as HTMLElement).classList.remove('active')
          }
        }
        this.sortKey = item.key as string
        this.sortMode = sortMode
        this.sortIndex = index
        const sortElement =
          this.$refs[`${sortMode === 'asc' ? 'asc' : 'desc'}_${index}`]
        if (sortElement && isArray(sortElement) && sortElement.length > 0) {
          ;(sortElement[0] as HTMLElement).classList.add('active')
        }
        this.$emit('sortchange', { key: this.sortKey, sort: this.sortMode })
      }
    },
    calcTableHeight() {
      const domBox = this.$el as HTMLElement | undefined
      if (domBox) {
        return domBox.offsetHeight - 10 - (this.noPage ? 0 : 48)
      }
      return 0
    },
    onpageChange() {
      this.$emit('pagechange', {
        pageSize: this.pageSize,
        pageNumber: this.currentPage,
      })
    },
    onShowNumberChange() {
      this.$emit('pagenumberchange', this.currentPage)
      this.onpageChange()
    },
    onShowSizeChange(...arguments_: any) {
      this.pageSize = (arguments_ as Array<any>)[1] as number
      this.currentPage = (arguments_ as Array<any>)[0] as number
      this.$emit('pagesizechange', (arguments_ as Array<any>)[1] as number)
      this.onpageChange()
    },
    onTableBoxScroll(event: any) {
      const headDiv = this.$refs.headdiv as HTMLElement
      if (headDiv) {
        headDiv.style.transform = `translateX(-${event.target.scrollLeft}px)`
      }
    },
    getUnitWidth() {
      if (
        this.config &&
        this.config.chartOptions &&
        this.config.chartOptions.columns
      ) {
        return Math.max(
          this.columnMinWidth,
          ((this.getWidth() as number) - 57) /
            this.config.chartOptions.columns.length
        )
      }
      return this.columnMinWidth
    },
    getWidth() {
      const element = this.$el as HTMLElement
      return element ? element.offsetWidth : 400
    },

    getColumnWidthData() {
      const config = this.config as any
      if (config.chartOptions.columnWidthData) {
        // 循环给对象增加响应式属性
        Object.keys(config.chartOptions.columnWidthData)?.forEach(
          (key: string) => {
            this.$set(
              this.columnWidthData,
              key,
              config.chartOptions.columnWidthData[key]
            )
          }
        )
      }
    },

    onColumnWidthChange(
      newWidth: number,
      oldWidth: number,
      column: { label: string }
    ) {
      this.columnWidthData = {
        ...this.columnWidthData,
        [column.label]: newWidth,
      }
      this.$emit('columnWidthChange', this.columnWidthData)
    },
  },
})
</script>
<style lang="less" scoped>
.page-table {
  background: var(--component-bg-color);
  height: 100%;
  padding: 0 18px;
  position: relative;
  width: 100%;

  .name {
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /deep/ .el-table {
    .el-table__header {
      .cell {
        padding: 0 6px;

        .header-label {
          color: #909399;
          font-size: 14px;
          font-weight: 700;
          height: 20px;
          line-height: 20px;
          overflow: hidden;
          padding: 0;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      }

      .cell .header-cell {
        display: flex;
        flex-flow: row nowrap;
        justify-content: flex-start;

        .caret-wrapper {
          height: 20px;

          .ascending {
            top: -4px;

            &.active {
              border-bottom-color: #5760e6;
            }
          }

          .descending {
            bottom: -4px;

            &.active {
              border-top-color: #5760e6;
            }
          }
        }
      }
    }

    .el-table__body-wrapper {
      width: 102%;

      &::-webkit-scrollbar {
        background: var(--table-tr);
        height: 8px;
        visibility: hidden;
        width: 8px;
      }

      &::-webkit-scrollbar-thumb {
        background: rgba(144, 147, 153, 0.5);
        border-radius: 8px;
        visibility: hidden;
      }

      &::-webkit-scrollbar-track {
        background: transparent;
        border-radius: 8px;
      }

      &::-webkit-scrollbar-corner {
        background-color: transparent;
      }

      td {
        padding: 0 !important;
      }
    }

    .el-table__body .el-table__row--striped td {
      background: #f3f3f3;
    }

    tbody .cell {
      color: #373b52;
      display: block;
      font-size: 14px;
      font-weight: 300;
      height: 26px;
      line-height: 26px;
      max-width: 100%;
      overflow: hidden;
      padding: 0 6px;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  /deep/ .plTableBox .el-table {
    th {
      background: var(--table-th);
    }

    tr {
      background: var(--table-tr);
    }

    .header-label {
      color: var(--table-pag-num) !important;
    }

    .cell {
      color: var(--table-pag-num) !important;
    }
  }

  /deep/ .ant-kg-appl-pagination-item.ant-kg-appl-pagination-item-active {
    background: var(--table-pag-active-num);

    a {
      color: #fff;
    }
  }

  /deep/ .ant-kg-appl-pagination-item a {
    color: var(--table-pag-num); //rgba(255,255,255,0.90);
  }

  /deep/ .ant-kg-appl-pagination.mini .ant-kg-appl-pagination-item-link {
    color: var(--table-pag-num);
  }

  /deep/ .el-table__body {
    tr:hover > td,
    .current-row > td {
      background-color: var(--table-row-hover);
    }
  }

  /deep/ .ant-kg-appl-pagination-item-ellipsis {
    color: #ccc;
  }

  /deep/ .plTableBox .el-table--border td,
  /deep/ .plTableBox .el-table--border th,
  /deep/
    .plTableBox
    .el-table__body-wrapper
    .el-table--border.is-scrolling-left
    ~ .el-table__fixed,
  /deep/ .plTableBox .el-table td,
  /deep/ .plTableBox .el-table .is-leaf,
  /deep/ .plTableBox .el-table--border,
  /deep/ .plTableBox .el-table--group {
    border-color: var(--table-border);
  }

  /deep/ .plTableBox .el-table,
  /deep/ .plTableBox .el-table__expanded-cell {
    background-color: transparent;
  }

  /deep/ .plTableBox .el-table--border::after,
  /deep/ .plTableBox .el-table--group::after,
  /deep/ .plTableBox .el-table::before {
    background-color: var(--table-border);
  }

  &:hover {
    /deep/ .el-table .el-table__body-wrapper {
      width: 100%;

      &::-webkit-scrollbar {
        background: var(--table-tr);
        visibility: visible;
      }

      &::-webkit-scrollbar-thumb {
        visibility: visible;
      }
    }
  }
}

.page-box {
  padding-top: 12px;
  text-align: right;
}
</style>
